home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / catclock / alarm.c next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  8.2 KB  |  508 lines

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <malloc.h>
  4.  
  5. #include <signal.h>
  6. #include <strings.h>
  7. #include <ctype.h>
  8. #include <sys/time.h>
  9.  
  10. #include <X11/Xlib.h>
  11. #include <X11/Xutil.h>
  12. #include <X11/Intrinsic.h>
  13.  
  14. #include <Xm/Xm.h>
  15.  
  16. #include "alarm.h"
  17. #include "bell.xbm"
  18.  
  19. /*
  20.  *  Various defines
  21.  */
  22. #define    ALARMBELLSEC    (1000000L / TEXTSCROLLTIME)
  23. #define    PAD        3
  24. #define    RECHECKTIME    (5 * 60)
  25. #define    SECONDSPERDAY    (60 * 60 * 24)
  26. #define    TEXTSCROLLTIME    250000L
  27.  
  28.  
  29. /*
  30.  *  Alarm structure
  31.  */
  32. typedef struct _Alarm {
  33.     long    alarmTime;
  34.     long    alarmSec;
  35.     char    *alarmAnnounce;
  36. } Alarm;
  37.  
  38.  
  39. #define TRUE 1
  40. #define FALSE 0
  41.  
  42.  
  43. /*
  44.  *  Globals (ugh!)
  45.  */
  46. static char    alarmBuf[BUFSIZ];
  47. static int     alarmBufLen;
  48.  
  49. static char     alarmFile[BUFSIZ];
  50.  
  51. static XFontStruct *alarmFontInfo;
  52.  
  53. static int     alarmIndex;
  54. static int     alarmLen;
  55. static int     alarmBell;
  56. static int     alarmBellCnt;
  57. static Boolean     *alarmOn;
  58. static Boolean     alarmRun;
  59. static Boolean     *alarmState;
  60. static int     alarmWidth;
  61.  
  62. static int     alarmX;
  63. static int     alarmY;
  64.  
  65. static int     foreground;
  66. static int     background;
  67.  
  68. static Boolean     bellFlash;
  69.  
  70. static int     bellX;
  71. static int     bellY;
  72.  
  73. static Alarm     nextAlarm;
  74. static Window     w;
  75.  
  76. static Pixmap     BellPixmap;
  77. static GC     eraseGC = 0;
  78.  
  79. extern Display *dpy;
  80. extern int     screen;
  81. extern Window     root;
  82. extern GC     gc;
  83.  
  84. static XmFontList xmFontList;
  85.  
  86.  
  87.  
  88. void InitBellAlarm(win, width, height, fontInfo, fontList, fg, bg, state, on)
  89.     Window     win;
  90.     int     width, height;
  91.     XFontStruct *fontInfo;
  92.     Pixel    fg, bg;
  93.     XmFontList    fontList;
  94.     Boolean     *state, *on;
  95. {
  96.     xmFontList = fontList;
  97.  
  98.     bellX = PAD;
  99.     bellY = PAD;
  100.  
  101.     alarmX = bell_width + 2 * PAD + fontInfo->max_bounds.width;
  102.     alarmY = PAD;
  103.  
  104.     w = win;
  105.  
  106.     alarmFontInfo = fontInfo;
  107.     alarmWidth = width - alarmX;
  108.  
  109.     foreground = fg;
  110.     background = bg;
  111.  
  112.     alarmLen = (alarmWidth + (fontInfo->max_bounds.width - 1)) /
  113.       fontInfo->max_bounds.width;
  114.     alarmOn    = on;
  115.     alarmState = state;
  116.     
  117.     if (!eraseGC) {
  118.     XGCValues xgcv;
  119.     
  120.     eraseGC = XCreateGC(dpy, w, 0,  &xgcv);
  121.     XCopyGC(dpy, gc, ~0, eraseGC);
  122.  
  123.     xgcv.foreground = bg;
  124.     xgcv.background = fg;
  125.     XChangeGC(dpy, eraseGC, GCForeground | GCBackground, &xgcv);
  126.     }
  127. }
  128.  
  129.  
  130.  
  131. void DrawBell(flash)
  132.     int flash;
  133. {
  134.     Boolean    i;
  135.     
  136.     if (!nextAlarm.alarmTime) {
  137.     return;
  138.     }
  139.     
  140.     i = flash ? (bellFlash = (bellFlash == TRUE) ? FALSE : TRUE) : TRUE;
  141.     
  142.     if (i == TRUE) {
  143.     if (!BellPixmap) {
  144.         BellPixmap = XCreateBitmapFromData(dpy, w,
  145.                            bell_bits,
  146.                            bell_width, bell_height);
  147.     }
  148.     XCopyPlane(dpy, BellPixmap, w, gc,
  149.            0, 0,
  150.            bell_width, bell_height,
  151.            bellX, bellY, 0x1);
  152.     } else {
  153.     extern void HideBell();
  154.     
  155.     HideBell();
  156.     }
  157. }
  158.  
  159.  
  160.  
  161. static void HideBell()
  162. {
  163.     XFillRectangle(dpy, w, eraseGC,
  164.            bellX, bellY, bell_width, bell_height);
  165.     XFlush(dpy);
  166. }
  167.  
  168.  
  169.  
  170. static void AlarmAnnounce()
  171. {
  172.     int         i, w;
  173.     char         buf[BUFSIZ];
  174.     struct itimerval     tv;
  175.     extern void        TextScroll();
  176.     
  177.     strcpy(buf, nextAlarm.alarmAnnounce ? nextAlarm.alarmAnnounce : "alarm");
  178.     strcat(buf, " ... ");
  179.     alarmBufLen = strlen(buf);
  180.  
  181.     w = XTextWidth(alarmFontInfo, buf, alarmBufLen);
  182.  
  183.     i = alarmWidth;
  184.     strcpy(alarmBuf, buf);
  185.  
  186.     do {
  187.     strcat(alarmBuf, buf);
  188.     } while ((i -= w) > 0);
  189.  
  190.     alarmIndex = -alarmLen;
  191.     sigset(SIGALRM, TextScroll);
  192.     
  193.     bzero((char *)&tv, sizeof(tv));
  194.     tv.it_interval.tv_usec = tv.it_value.tv_usec = TEXTSCROLLTIME;
  195.     setitimer(ITIMER_REAL, &tv, (struct itimerval *)NULL);
  196.     
  197.     alarmRun = TRUE;
  198.  
  199.     if (alarmOn) {
  200.     *alarmOn = TRUE;
  201.     }
  202.     if (alarmBell) {
  203.     XBell(dpy, 25);
  204.     alarmBellCnt = ALARMBELLSEC * alarmBell;
  205.     }
  206. }
  207.  
  208.  
  209.  
  210.  
  211. static void TextScroll()
  212. {
  213.     int     x, index;
  214.     XmString    xmString;
  215.     
  216.     if (alarmRun == FALSE) {
  217.     return;
  218.     }
  219.     if (++alarmIndex < 0) {
  220.     x = alarmX - alarmIndex * alarmFontInfo->max_bounds.width;
  221.     index = 0;
  222.     } else {
  223.     if (alarmIndex >= alarmBufLen) {
  224.         alarmIndex -= alarmBufLen;
  225.     }
  226.     x = alarmX;
  227.     index = alarmIndex;
  228.     }
  229.     
  230.     DrawBell(TRUE);
  231.     
  232.     xmString = XmStringCreate(&alarmBuf[index], XmSTRING_ISO8859_1);
  233.     XmStringDrawImage(dpy, w, xmFontList, xmString, gc,
  234.               x, alarmY, 1024,
  235.               XmALIGNMENT_BEGINNING,
  236.               XmSTRING_DIRECTION_L_TO_R, NULL);
  237.     XmStringFree(xmString);
  238.     
  239.     if (alarmBell && --alarmBellCnt <= 0) {
  240.     XBell(dpy, 25);
  241.     alarmBellCnt = ALARMBELLSEC * alarmBell;
  242.     }
  243.     XFlush(dpy);
  244. }
  245.  
  246.  
  247.  
  248. static void ReadAlarmFile(file)
  249.     char    *file;
  250. {
  251.     char    *cp, *tp, *dp;
  252.     int     hour, minute, pm, day;
  253.     FILE     *fp;
  254.     struct tm     *tm;
  255.     long     l, l0;
  256.     time_t    clock;
  257.     char    buf[BUFSIZ];
  258.     
  259.     if (nextAlarm.alarmAnnounce) {
  260.     free((void *)(nextAlarm.alarmAnnounce));
  261.     }
  262.     bzero((char *)&nextAlarm, sizeof(nextAlarm));
  263.  
  264.     if (!file || !(fp = fopen(file, "r"))) {
  265.     return;
  266.     }
  267.  
  268.     time(&clock);
  269.     tm = localtime(&clock);
  270.     
  271.     l0 = clock - (60 * (60 * tm->tm_hour + tm->tm_min) + tm->tm_sec);
  272.     
  273.     while (fgets(buf, sizeof(buf), fp)) {
  274.     if (*buf == '#' || !(cp = index(buf, ':')) ||
  275.         !(tp = index(buf, '\t')) || tp < cp) {
  276.         continue;
  277.     }
  278.     
  279.     dp = buf;
  280.     while (isspace(*dp)) {
  281.         dp++;
  282.     }
  283.     
  284.     switch (*dp) {
  285.         case 'S':
  286.         case 's': {
  287.         day = (dp[1] == 'a' || dp[1] == 'A') ? 6 : 0;
  288.         break;
  289.         }
  290.         case 'M':
  291.         case 'm': {
  292.         day = 1;
  293.         break;
  294.         }
  295.         case 'T':
  296.         case 't': {
  297.         day = (dp[1] == 'h' || dp[1] == 'H') ? 4 : 2;
  298.         break;
  299.         }
  300.         case 'W':
  301.         case 'w': {
  302.         day = 3;
  303.         break;
  304.  
  305.         }
  306.         case 'F':
  307.         case 'f': {
  308.         day = 5;
  309.         break;
  310.         }
  311.         default: {
  312.         day = -1;
  313.         break;
  314.         }
  315.     }
  316.  
  317.     while (!isdigit(*dp) && dp < cp) {
  318.         dp++;
  319.     }
  320.     *cp++ = 0;
  321.     *tp++ = 0;
  322.  
  323.     while (isspace(*cp)) {
  324.         cp++;
  325.     }
  326.  
  327.     if ((minute = atoi(cp)) < 0) {
  328.         minute = 0;
  329.     } else if (minute > 59) {
  330.         minute = 59;
  331.     }
  332.  
  333.     while (isdigit(*cp)) {
  334.         cp++;
  335.     }
  336.  
  337.     while (isspace(*cp)) {
  338.         cp++;
  339.     }
  340.  
  341.     pm = (*cp == 'p' || *cp == 'P');
  342.  
  343.     if ((hour = atoi(dp)) < 0) {
  344.         hour = 0;
  345.     } else if (hour < 12) {
  346.         if (pm) {
  347.         hour += 12;
  348.         }
  349.     } else if (hour == 12) {
  350.         if (!pm) {
  351.         hour = 0;
  352.         }
  353.     } else if (hour > 23) {
  354.         hour = 23;
  355.     }
  356.  
  357.     l = l0 + 60 * (60 * hour + minute);
  358.  
  359.     if (day < 0) {
  360.         if (l < clock) {
  361.         l += SECONDSPERDAY;
  362.         }
  363.     } else {
  364.         if (day < tm->tm_wday || (day == tm->tm_wday && l < clock)) {
  365.         day += 7;
  366.         }
  367.         l += (day - tm->tm_wday) * SECONDSPERDAY;
  368.     }
  369.     
  370.     if (nextAlarm.alarmTime && l >= nextAlarm.alarmTime) {
  371.         continue;
  372.     }
  373.     if (nextAlarm.alarmAnnounce) {
  374.         free((void *)(nextAlarm.alarmAnnounce));
  375.     }
  376.     nextAlarm.alarmTime = l;
  377.     
  378.     while (isspace(*tp)) {
  379.         tp++;
  380.     }
  381.  
  382.     if (cp = index(tp, '\n')) {
  383.         *cp = 0;
  384.     }
  385.  
  386.     for (cp = tp + strlen(tp) - 1 ; cp >= tp && isspace(*cp) ; ) {
  387.         *cp-- = 0;
  388.     }
  389.  
  390.     if (!*tp) {
  391.         continue;
  392.     }
  393.  
  394.     if (nextAlarm.alarmAnnounce = malloc(strlen(tp) + 1)) {
  395.         strcpy(nextAlarm.alarmAnnounce, tp);
  396.     }
  397.     }
  398.  
  399.     fclose(fp);
  400.     
  401.     if (nextAlarm.alarmTime) {
  402.     nextAlarm.alarmSec = nextAlarm.alarmTime - clock;
  403.     }
  404. }
  405.  
  406.  
  407.  
  408. void SetAlarm(file)
  409.     char    *file;
  410. {
  411.     extern void Set_Alarm();
  412.  
  413.     ReadAlarmFile(file);
  414.     
  415.     if (!nextAlarm.alarmTime) {
  416.     *alarmFile = 0;
  417.     if (alarmState) {
  418.         *alarmState = FALSE;
  419.     }
  420.     AlarmOff();
  421.     HideBell();
  422.     
  423.     return;
  424.     }
  425.     
  426.     strcpy(alarmFile, file);
  427.     
  428.     DrawBell(FALSE);
  429.     Set_Alarm();
  430. }
  431.  
  432.  
  433.  
  434. static void ResetAlarm()
  435. {
  436.     extern void Set_Alarm();
  437.     
  438.     if (!*alarmFile) {
  439.     return;
  440.     }
  441.     ReadAlarmFile(alarmFile);
  442.     
  443.     if (!nextAlarm.alarmTime) {
  444.     *alarmFile = 0;
  445.     if (alarmState) {
  446.         *alarmState = FALSE;
  447.     }
  448.     HideBell();
  449.  
  450.     return;
  451.     }
  452.  
  453.     Set_Alarm();
  454. }
  455.  
  456.  
  457.  
  458. static void Set_Alarm()
  459. {
  460.     struct itimerval tv;
  461.     
  462.     if (alarmState) {
  463.     *alarmState = TRUE;
  464.     }
  465.     if (nextAlarm.alarmSec > RECHECKTIME + 60) {
  466.     nextAlarm.alarmSec = RECHECKTIME;
  467.     sigset(SIGALRM, ResetAlarm);
  468.     } else {
  469.     sigset(SIGALRM, AlarmAnnounce);
  470.     }
  471.     
  472.     bzero((char *)&tv, sizeof(tv));
  473.     tv.it_value.tv_sec = nextAlarm.alarmSec;
  474.     setitimer(ITIMER_REAL, &tv, (struct itimerval *)NULL);
  475. }
  476.  
  477.  
  478.  
  479. void GetBellSize(bw, bh)
  480.     int *bw, *bh;
  481. {
  482.     *bw = bell_width +  2 * PAD;
  483.     *bh = bell_height + 2 * PAD;
  484. }
  485.  
  486.  
  487.  
  488. void SetBell(seconds)
  489.     int seconds;
  490. {
  491.     alarmBell = seconds;
  492. }
  493.  
  494.  
  495. void AlarmOff()
  496. {
  497.     struct itimerval tv;
  498.     
  499.     alarmRun = FALSE;
  500.  
  501.     if (alarmOn) {
  502.     *alarmOn = FALSE;
  503.     }
  504.  
  505.     bzero((char *)&tv, sizeof(tv));
  506.     setitimer(ITIMER_REAL, &tv, (struct itimerval *)NULL);
  507. }
  508.